module.exports = app => {
  const express = require("express")
  //token有关的包
  const jwt = require('jsonwebtoken')
  //抛出异常的包
  const assert = require('http-assert')
  //上传图片资源的包
  const multer = require('multer')
  const AdminUser = require('../../models/AdminUser')
  //使用子路由
  const router = express.Router({
    //特殊参数，表示合并URL参数，不加的话下边${req.params.resource}获取不到所需参数
    mergeParams: true
  })

  //通用的请求处理接口
  router.get('/', async (req, res) => {
    //分类列表的请求处理接口,并不是所有的页面都会查整条数据
    const queryOptions = {}
    if (req.Model.modelName === 'Category') {//(modelName是数据库表的一个属性，表示表名)
      queryOptions.populate = 'parent'
    }
    const items = await req.Model.find().setOptions(queryOptions).limit(100)
    res.send(items)
  })

  router.post('/', async (req, res) => {
    const model = await req.Model.create(req.body)
    res.send(model)
  })

  router.get('/:id', async (req, res) => {
    const model = await req.Model.findById(req.params.id)
    res.send(model)
  })

  router.put('/:id', async (req, res) => {
    const model = await req.Model.findByIdAndUpdate(req.params.id, req.body)
    res.send(model)
  })

  router.delete('/:id', async (req, res) => {
    //删过之后不需要获取返回值，直接返回给客户端一个成功的状态即可
    await req.Model.findByIdAndDelete(req.params.id, req.body)
    res.send({
      success: true
    })
  })

  //验证用户登录中间件（token）
  const authMiddleware = require('../../middleware/auth')
  //通过前端传递过来的路径加载所需的数据库数据模型的中间件
  const resourceMiddleware = require('../../middleware/resource')
  //挂载子路由
  app.use('/admin/api/rest/:resource', authMiddleware(), resourceMiddleware(), router)

  //上传图片资源的接口cnpm i multer(专门处理上传资源的中间件)
  const upload = multer({ dest: __dirname + '/../../uploads' })
  app.post('/admin/api/upload', authMiddleware(), upload.single('file'), async (req, res) => {
    const file = req.file
    //拼一个图片地址，供前端展示
    file.url = `http://localhost:3000/uploads/${file.filename}`
    res.send(file)
  }),

  //登录接口
  app.post('/admin/api/login', async (req, res) => {
    const { username, password } = req.body
    // 1.根据用户名查用户
    //findOne查找一条，在数据库中找键为ursename的数据，在其中寻找值为ursename的数据,因为默认密码无法查询出来，所以select('+password')表示将密码一并查出来
    const user = await AdminUser.findOne({ username }).select('+password')
    //使用抛出异常方式
    assert(user, 422, '用户不存在')
    // 2.校验密码(compareSync第一个参数时前端传来的明文密码，第二个参数时数据库中密文密码，比较返回一个布尔值)
    const isValid = require('bcryptjs').compareSync(password, user.password)
    assert(isValid, 422, '密码错误')
    // 3.返回token(首先cnpm i jsonwebtoken -S)
    //sign方法生成token，第一个参数为要保存的信息（可以是任意信息），第二个参数秘钥（为app全局注册一个变量用来做秘钥）
    const token = jwt.sign({ id: user.id }, app.get('secret'))
    res.send({ token, username })
  })


  //抛出的异常的处理(err.statusCode是异常的状态码，err.message是异常的信息就是上面抛出异常时的第三个参数)
  app.use(async (err, req, res, next) => {
    res.status(err.statusCode || 500).send({
      message: err.message
    })
  })
}